# -*-Perl-*-

package GenomeFiles::Processor::ncbi_genbank;

use GenomeFiles::Processor;
use File::Spec;
use Bio::SeqIO;
use Bio::SeqFeature::Tools::Unflattener;

use constant MRNA => 'mRNA';
use constant GENE => 'gene';
use constant CDS  => 'cds';
use constant EXON  => 'exon';
use constant MIN_LENGTH => 10_000;


use base qw(GenomeFiles::Processor);

our %Defaults = ('Format_dir' => 'nbci',
		 'format_suffix' => qr/\.(gbk|gb)(\.\w+)?/i,
		 'source'     => 'genbank',
		 'seqformat'  => 'genbank',
		 'chrom_src'  => 'assembly',
		 'chrom_type' => 'chromosome',

    );


sub _initialize {
    my $self = shift;
    $self->SUPER::_initialize(@_);
    my ($suffix) = $self->_rearrange([qw(FORMAT_SUFFIX)],@_);
    $self->format_suffix($suffix || $Defaults{'format_suffix'});

    
    # generate an Unflattener object
    my $unflattener = Bio::SeqFeature::Tools::Unflattener->new;
    $unflattener->error_threshold(1);
    $self->_unflattner($unflattner);

    # set module specific defaults
    
    if( ! $self->format_dir ) {
	$self->format_dir($Defaults{'format_dir'});
    }
}

sub process {
    my $self = shift;
    my $dir = $self->directory;
    my $raw = $self->rawfile_prefix;
    my $fdir = $self->format_dir
    my $rawncbidir = File::Spec->catdir($dir,$raw,$fdir)
    opendir(DIR, $dir) || $self->throw("Cannot open directory $dir: $!");
    my $suffix = $self->format_suffix;
    my $gffversion = $self->gff_version;
    my %features;
    for my $file ( readdir(DIR) ) {
	if( $file =~ $suffix ) {
	    warn "$file\n";
	    my $fullpath = File::Spec->catfile($rawncbidir,$file);
	    my $fh = $self->open_file($fullpath);
	    my $seqio = Bio::SeqIO->new(-format => $Defaults{'seqformat'},
					-fh     => $fh);
	    while( my $seq = $seqio->next_seq ) {
		my $desc = $seq->description;
		if( $desc =~ /(?:chromosome|contig)\s+([\w\d\.]+)/) {
		    $seq->display_id("$pref\_$1");
		}
		
		{ # process the chromosome
		    my $groupfield;
		    if( $gff_version == 3 ) {
			$groupfield = sprintf("ID=%s;Name=%s",
					      $seq->display_id,$seq->display_id);
		    } else {
			$groupfield = sprintf("Sequence %s",$seq->display_id);
		    }
		    push @{$features{'chromosome'}},
		    join("\t", ($seq->display_id,
				$Defaults{'chrom_src'},
				$Defaults{'chrom_type'},
				1,
				$seq->length,
				'.','.','.', # score, strand, frame
				$groupfield));
		
		}
		
		my @top_sfs = $seq->get_SeqFeatures;
		unless( $seq->length > MIN_LENGTH &&
			grep { $_->primary_tag eq 'gene' } @top_sfs) {
		    next;
		}
	    }
	}
    }
    
}

sub write {

}


=head2 format_suffix

 Title   : format_suffix
 Usage   : $obj->format_suffix($newval)
 Function: Get/Set suffix pattern
 Example : 
 Returns : value of format_suffix (a scalar)
 Args    : on set, new value (a scalar or undef, optional)


=cut

sub format_suffix{
    my $self = shift;

    return $self->{'format_suffix'} = shift if @_;
    return $self->{'format_suffix'};
}


=head2 _unflattener

 Title   : _unflattener
 Usage   : $obj->_unflattener($newval)
 Function: 
 Example : 
 Returns : value of _unflattener (a scalar)
 Args    : on set, new value (a scalar or undef, optional)


=cut

sub _unflattener{
    my $self = shift;

    return $self->{'_unflattener'} = shift if @_;
    return $self->{'_unflattener'};
}

sub _uniqlst { 
    my %x;
    return grep { ! $x{$_}++}  @_;
}

sub _escape {
    
    for my $value ( @_) {
        if(  defined $value && length($value) ) { 
            if ($value =~ /[^a-zA-Z0-9\,\;\=\.:\%\^\*\$\@\!\+\_\?\-]/) {
                $value =~ s/\t/\\t/g;       # substitute tab and newline 
                # characters
                $value =~ s/\n/\\n/g;       # to their UNIX equivalents
                
# Unescaped quotes are not allowed in GFF3
#                   $value = '"' . $value . '"';
            }
            $value =~ s/([\t\n\r%&\=;,])/sprintf("%%%X",ord($1))/ge;
        } 
    }
    return @_;
}


1;

